package com.k8.exchange;

import com.k8.rpc.invoke.invocation.Invocation;
import com.k8.rpc.invoke.invocation.RpcInvocationTemplate;
import com.k8.rpc.invoke.invocation.RpcInvocationTemplateManager;
import com.k8.rpc.result.Result;
import com.k8.rpc.serialize.Serializer;
import com.key.w8.http1.entity.HttpRequest;
import com.key.w8.http1.entity.HttpResponse;
import com.key.w8.http1.handler.codec.ByteBufAllocatorHolder;
import com.key.w8.http1.handler.codec.HttpObjectServerResolver;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.*;

import static com.k8.exchange.constants.HeaderConstants.INVOCATION_KEY;
import static com.k8.exchange.constants.HeaderConstants.SERIALIZER_KEY;
import static com.key.w8.http1.entity.HttpObject.DataContentType.COMPLEX_OBJECT_FROM_READ;

/**
 * @Author: k8
 * @CreateTime: 2025-08-15
 * @Version: 1.0
 */
public class SerializeServerResolver implements HttpObjectServerResolver {
    private Serializer serializer;
    private RpcInvocationTemplateManager rpcInvocationTemplateManager;

    public SerializeServerResolver(Serializer serializer, RpcInvocationTemplateManager rpcInvocationTemplateManager) {
        this.serializer = serializer;
        this.rpcInvocationTemplateManager = rpcInvocationTemplateManager;
    }

    @Override
    public boolean canResolverRequestIn(FullHttpRequest fullHttpRequest) {
        HttpHeaders headers = fullHttpRequest.headers();
        if (!headers.contains(INVOCATION_KEY) || !rpcInvocationTemplateManager.containsInvocation(headers.get(INVOCATION_KEY)) ||
                !headers.contains(SERIALIZER_KEY) || serializer.serializerName() == null || !serializer.serializerName().equals(headers.get(SERIALIZER_KEY))) {
            return false;
        }
        return true;
    }

    @Override
    public HttpRequest resolverRequestIn(FullHttpRequest fullHttpRequest) {
        HttpRequest request = new HttpRequest(fullHttpRequest.headers(), fullHttpRequest.protocolVersion(), fullHttpRequest.method(), fullHttpRequest.uri());
        ByteBuf content = fullHttpRequest.content();
        String invocationKey = fullHttpRequest.headers().get(INVOCATION_KEY);
        RpcInvocationTemplate templateInvocation = (RpcInvocationTemplate) rpcInvocationTemplateManager.getInvocation(invocationKey);
        Invocation invocation = serializer.decode(content, Invocation.class);
        invocation.setTemplate(templateInvocation);
        request.setComplexObject(invocation);
        return request;
    }

    @Override
    public boolean canResolverResponseOut(HttpResponse httpResponse) {
        if (httpResponse.contentType().equals(COMPLEX_OBJECT_FROM_READ) && httpResponse.complexObject() instanceof Result)
            return true;
        return false;
    }

    @Override
    public FullHttpResponse resolverResponseOut(HttpResponse httpResponse, ByteBufAllocatorHolder byteBufAllocatorHolder) {
        httpResponse.headers().add("k8Protocol", true);
        Result result = (Result) httpResponse.complexObject();
        ByteBuf buffer = byteBufAllocatorHolder.alloc().buffer();
        ByteBuf encode = serializer.encode(result, buffer);
        DefaultFullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(httpResponse.version(), httpResponse.status(), encode, httpResponse.headers(), EmptyHttpHeaders.INSTANCE);
        fullHttpResponse.headers().add(HttpHeaderNames.CONTENT_LENGTH, encode.readableBytes());
        return fullHttpResponse;
    }


}
